package cn.sp;

import cn.sp.constants.AdminConstants;
import cn.sp.constants.NacosConstants;
import cn.sp.exception.ShipException;
import cn.sp.pojo.dto.RegisterAppDTO;
import cn.sp.pojo.dto.UnregisterAppDTO;
import cn.sp.utils.IpUtil;
import cn.sp.utils.OkhttpTool;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by 2YSP on 2020/12/21
 */
public class RegisterUtils {

    private final static Logger LOGGER = LoggerFactory.getLogger(RegisterUtils.class);

    /**
     * register all interface info to register center
     */
    public static void doRegister(NamingService namingService, ClientConfigProperties properties) {
        Instance instance =  createInstance(properties);
        registInterfaceToNacos(namingService, instance, properties);
        LOGGER.info("register interface info to nacos success!");
		postRegistToServer(instance, properties);
        LOGGER.info("register to ship-admin success!");
    }
	
	 public static void registerShutDownHook(ClientConfigProperties properties) {
        final UnregisterAppDTO unregisterAppDTO = createUnRegistDTO(properties);
        postUnregist(unregisterAppDTO, properties);
	 }
	 
	 private static UnregisterAppDTO createUnRegistDTO(ClientConfigProperties properties) {
        final UnregisterAppDTO unregisterAppDTO = new UnregisterAppDTO();
        unregisterAppDTO.setAppName(properties.getAppName());
        unregisterAppDTO.setVersion(properties.getVersion());
        unregisterAppDTO.setIp(IpUtil.getLocalIpAddress());
        unregisterAppDTO.setPort(properties.getPort());
		return unregisterAppDTO;
	 }
	 
	 private static void postUnregist(UnregisterAppDTO unregisterAppDTO, ClientConfigProperties properties) {
        final String url = "http://" + properties.getAdminUrl() + AdminConstants.UNREGISTER_PATH;
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            OkhttpTool.doPost(url, unregisterAppDTO);
            LOGGER.info("[{}:{}] unregister from ship-admin success!", unregisterAppDTO.getAppName(), unregisterAppDTO.getVersion());
        }));
	 }
    
	
	private static Instance createInstance(ClientConfigProperties properties) {
        Instance instance = new Instance();
        instance.setIp(IpUtil.getLocalIpAddress());
        instance.setPort(properties.getPort());
        instance.setEphemeral(true);
        Map<String, String> metadataMap = new HashMap<>();
        metadataMap.put("version", properties.getVersion());
        metadataMap.put("appName", properties.getAppName());
        instance.setMetadata(metadataMap);
		return instance;
	}
	
	private static void registInterfaceToNacos(NamingService namingService, Instance instance, ClientConfigProperties properties) {
        try {
            namingService.registerInstance(properties.getAppName(), NacosConstants.APP_GROUP_NAME, instance);
        } catch (NacosException e) {
            LOGGER.error("register to nacos fail", e);
            throw new ShipException(e.getErrCode(), e.getErrMsg());
        }
	}
	
	private static void postRegistToServer(Instance instance, ClientConfigProperties properties) {
        String url = "http://" + properties.getAdminUrl() + AdminConstants.REGISTER_PATH;
        RegisterAppDTO registerAppDTO = buildRegisterAppDTO(instance);
        OkhttpTool.doPost(url, registerAppDTO);
	}


    private static RegisterAppDTO buildRegisterAppDTO(Instance instance, ClientConfigProperties properties) {
        RegisterAppDTO registerAppDTO = new RegisterAppDTO();
        registerAppDTO.setAppName(properties.getAppName());
        registerAppDTO.setContextPath(properties.getContextPath());
        registerAppDTO.setIp(instance.getIp());
        registerAppDTO.setPort(instance.getPort());
        registerAppDTO.setVersion(properties.getVersion());
        return registerAppDTO;
    }
}
